﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.IO.Ports;
using System.Windows.Forms;
using System.Threading;
using System.Reflection;
using System.ComponentModel;
using System.Collections;
using Collector.Device;

namespace Collector
{
    public class ComPortPack : IDeviceConnector
    {
        /// <summary>
        /// 提供对串口的统一访问
        /// </summary>
        #region 事件和字段定义
        public event PortDataReceivedEventHandle Received;
        public SerialPort serialPort = new SerialPort();
        public bool ReceiveEnableFlag = true;  //接收事件是否有效 true表示有效
        #endregion

        public IPulseCollectorFactory collector = null;

        public class SerialPortModel
        {
            /// <summary>
            /// 端口号
            /// </summary>
            //public Dictionary<string, double> dictPulsePressData_ { get; set; }
            /// <summary>
            /// 端口号
            /// </summary>
            public string PortName { get; set; }

            /// <summary>
            /// 波特率
            /// </summary>
            public int BaudRate { get; set; }

            /// <summary>
            /// 奇偶验证
            /// </summary>
            public Parity Parity { get; set; }

            /// <summary>
            /// 停止位
            /// </summary>
            public StopBits StopBits { get; set; }

            /// <summary>
            /// 数据位
            /// </summary>
            public int DataBits { get; set; }
        }

        #region 构造函数
        public ComPortPack()
        {

        }

        //private 确保该类无法被其它类新建出新的实例
        public ComPortPack(SerialPortModel entity)
        {
            //LoadSerialPort();
            serialPort.PortName = entity.PortName;
            serialPort.BaudRate = entity.BaudRate;
            serialPort.Parity = entity.Parity;
            serialPort.StopBits = entity.StopBits;
            serialPort.NewLine = "\r\n";
            serialPort.DataReceived += SerialPort_DataReceived;
            serialPort.ReceivedBytesThreshold = 1;
            serialPort.Handshake = Handshake.None;
            serialPort.DataBits = entity.DataBits;
            serialPort.DtrEnable = true;
            serialPort.RtsEnable = true;
        }

        private void SerialPort_DataReceived(object sender, SerialDataReceivedEventArgs e)
        {
            try
            {
                int readCount = serialPort.BytesToRead;
                byte[] data = new byte[readCount];
                int needReadSize = serialPort.Read(data, 0, data.Length);
                if (Received != null)
                {
                    //Log.Debug("needReadSize :" + needReadSize);
                    Received(sender, new PortDataReciveEventArgs(data, needReadSize, collector));
                }
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message.ToString());
            }
        }
        #endregion

        #region 串口操作集合

        /// <summary>
        /// 返回串口对象的单个实例
        /// </summary>
        /// <returns></returns>
        public static ComPortPack GetComPortPack()
        {
            return null;
        }

        /// <summary>
        /// 释放串口资源
        /// </summary>
        ~ComPortPack()
        {
            Close();
        }

        /// <summary>
        /// 打开串口
        /// </summary>
        public bool Open()
        {
            try
            {
                if (!serialPort.IsOpen)
                {
                    Log.Debug("serialPort.IsOpen :"+ serialPort.IsOpen);
                    serialPort.Open();
                }
            }
            catch (Exception)
            {
                return false;
            }
            return true;
        }

        /// <summary>
        /// 关闭串口
        /// </summary>
        public void Close()
        {
            //try catch block
            if (IsOpen())
            {
                try
                {
                    serialPort.Close();
                }
                catch (Exception) 
                {
                    // No-nothing
                }
            }
        }

        public void DiscardInBuffer()
        {
            //try catch block
            if (serialPort.IsOpen)
            {
                try
                {
                    serialPort.DiscardInBuffer();
                }
                catch (Exception) { }
            }
        }

        /// <summary>
        /// 串口是否打开
        /// </summary>
        /// <returns></returns>
        public bool IsOpen()
        {
            return serialPort.IsOpen;
        }

        public  void SendData(byte[] data)
        {
            try
            {
                if (IsOpen())
                {
                    serialPort.Write(data, 0, data.Length);
                }
            }
            catch (Exception ex)
            {
                throw ex;
            }
        }

        public void SendData(string data)
        {
            //禁止接收事件时直接退出
            if (IsOpen())
            {
                serialPort.Write(data);
            }
        }

        public void SendData(byte[] data, int offset, int count)
        {
            if (IsOpen())
            {
                serialPort.Write(data, offset, count);
            }
        }
        #endregion

        /// <summary>
        /// 对于指定类中自定义事件，移除其中的委托链的全部订阅方法，
        /// 或者移除委托链中的指定方法名的订阅。
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="c"></param>
        /// <param name="event_name"></param>
        /// <param name="methodname"></param>
        public static void RemoveEvent<T>(T c, string event_name, string methodname = "")
        {
            Delegate[] invokeList = GetObjectEventList_V2(c, event_name);
            if (invokeList == null) return;

            foreach (Delegate del in invokeList)
            {
                if (methodname != "" && del.Method.Name != methodname)
                    continue;
                typeof(T).GetEvent(event_name).RemoveEventHandler(c, del);
                //Console.WriteLine("Remove an event of " + event_name);
            }
        }

        public static Delegate[] GetObjectEventList_V2(object p_object, string p_EventName)
        {
            FieldInfo _fieldInfo;
            Delegate _ObjDele;
            object _FieldValue;

            _fieldInfo = p_object.GetType().GetField(p_EventName, BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Static | BindingFlags.Public);
            if (_fieldInfo == null) return null;
            _FieldValue = _fieldInfo.GetValue(p_object);

            if (_FieldValue == null || !(_FieldValue is Delegate)) return null;
            _ObjDele = (Delegate)_FieldValue;

            return _ObjDele.GetInvocationList();
        }

        /// <summary>
        /// 获取窗体控件的注册事件名称。
        /// 例如：按钮的单击事件：
        /// GetObjectEventList<Control>(button1, "Click");
        /// 菜单项的单击事件：
        /// GetObjectEventList<System.Windows.Forms.ToolStripItem>(menuStrip1.Items[0], "Click");
        /// 不同的控件的基类也不相同，在使用的时候应格外注意，否则将返回Null
        /// 另外，我这里方法内部使用了EventClick的事件记录，在使用的时候最好还是调试看看事件名称是否匹配
        /// Delegate[] d1 = EventTest.GetObjectEventList<System.Windows.Forms.Control>(btnTest, "Click");
        ///  Delegate[] d2 = EventTest.GetObjectEventList<System.Windows.Forms.ToolStripItem>(menuStrip1.Items[0], "Click");
        /// </summary>
        /// <typeparam name="T">表示事件所定义的类</typeparam>
        /// <param name="pControl">控件实例，或事件的子类</param>
        /// <param name="pEventName">事件名称</param>
        /// <returns></returns>
        private Delegate[] GetObjectEventList<T>(T pControl, string pEventName)
        {
            Delegate[] ret = null;
            Type ctlType = typeof(T);
            PropertyInfo _PropertyInfo = ctlType.GetProperty("Events", BindingFlags.Instance | BindingFlags.NonPublic);
            if (_PropertyInfo != null)
            {
                EventHandlerList _EventList = _PropertyInfo.GetValue(pControl, null) as EventHandlerList;
                FieldInfo _FieldInfo = ctlType.GetField("Event" + pEventName, BindingFlags.Static | BindingFlags.NonPublic);
                if (_EventList != null && _EventList is EventHandlerList && _FieldInfo != null)
                {
                    Delegate _ObjectDelegate = _EventList[_FieldInfo.GetValue(pControl)];
                    if (_ObjectDelegate != null)
                        ret = _ObjectDelegate.GetInvocationList();
                }
            }
            return ret;
        }
        /// <summary>
        /// 查找控件的对应的事件注册的方法名
        /// </summary>
        /// <param name="control">控件</param>
        /// <param name="eventName">事件</param>
        /// <returns>返回事件注册的方法名，若未找到则返回null</returns>
        private static string GetBindingMethod(Control control, string eventName)
        {
            //EventInfo info = control.GetType().GetEvent(eventName);
            PropertyInfo propertyInfo = control.GetType().GetProperty("Events", BindingFlags.Instance | BindingFlags.NonPublic);
            if (propertyInfo == null) { return null; }

            EventHandlerList eventList = (EventHandlerList)propertyInfo.GetValue(control, null);
            FieldInfo fieldInfo = typeof(Control).GetField("Event" + eventName, BindingFlags.Static | BindingFlags.NonPublic);
            if (fieldInfo == null) { return null; }

            Delegate delegateInfo = eventList[fieldInfo.GetValue(control)];
            if (delegateInfo == null) { return null; }
            Delegate[] delegateList = delegateInfo.GetInvocationList();

            return delegateList[delegateList.Length - 1].Method.Name;
        }

    }

    public delegate void PortDataReceivedEventHandle(object sender, PortDataReciveEventArgs e);

    public class PortDataReciveEventArgs : EventArgs
    {
        private IPulseCollectorFactory mCollector;

        private byte[] data;

        public byte[] Data
        {
            get { return data; }
            set { data = value; }
        }
        private int receiveDataSize;

        public int ReceiveDataSize
        {
            get { return receiveDataSize; }
            set { receiveDataSize = value; }
        }

        public PortDataReciveEventArgs()
        {
            this.data = null;
        }
        public PortDataReciveEventArgs(byte[] data, int readSize, IPulseCollectorFactory factory=null)
        {
            this.data = data;
            this.receiveDataSize = readSize;
            this.mCollector = factory;
        }

        public IPulseCollectorFactory CollectorInstanceGet()
        {
            return mCollector;
        }
    }

    public static class ConvertFuncs
    {

        ///byte 转换为 16进制
        public static string ToHexString(byte b)
        {
            return Convert.ToString(b, 16);
        }

        ///int 转换为 16进制
        public static string ToHexString(int num)
        {
            return Convert.ToString(num, 16);
        }
        ///int 转换为 byte
        public static byte intToByte(int num)
        {
            return Convert.ToByte(num);
        }

        ///16进制字符串 转换为 字节数组
        public static byte[] HexStringToByteArray(string s)
        {
            s = s.Replace(" ", "");
            byte[] buffer = new byte[s.Length / 2];
            for (int i = 0; i < s.Length; i += 2)
            {
                buffer[i / 2] = (byte)Convert.ToByte(s.Substring(i, 2), 16);
            }
            return buffer;
        }

        //字节数组 转换成 16进制字符串
        public static string ByteArrayToHexString(byte[] data)
        {
            StringBuilder sb = new StringBuilder(data.Length * 3);
            foreach (byte b in data)
            {
                sb.Append(Convert.ToString(b, 16).PadLeft(2, '0').PadRight(3, ' '));
            }
            return sb.ToString().Trim().ToUpper();
        }

        //ASCII 转换成 16进制
        public static string AsciiToHex(string ascii)
        {
            char[] cs = ascii.ToCharArray();
            StringBuilder sb = new StringBuilder();
            for (int i = 0; i < cs.Length; i++)
            {
                string hex = ((int)cs[i]).ToString("X");
                sb.AppendFormat("{0} ", hex);
            }
            return sb.ToString().TrimEnd(' ');
        }

        //16进制 转换为 ASCII
        public static string HexToAscii(string hex)
        {
            if (hex.Length % 2 == 0)
            {
                int iValue;
                byte[] bs;
                string sValue = string.Empty;
                string result = string.Empty;
                int length = hex.Length / 2;

                for (int i = 0; i < length; i++)
                {
                    iValue = Convert.ToInt32(hex.Substring(i * 2, 2), 16);   //16进制->10进制
                    bs = System.BitConverter.GetBytes(iValue);               //int -> byte[]
                    sValue = System.Text.Encoding.ASCII.GetString(bs, 0, 1); //byte[] -> ASCII
                    result += char.Parse(sValue).ToString();
                }
                return result.PadLeft(length, '0');
            }
            return string.Empty;
        }

        ///以下2个函数根据具体情况使用 输入字符长度为8
        //ASCII 转换为 float 
        public static float AsciiToFloat(string ascii)
        {
            if (ascii.Length == 8)
            {
                byte[] arr = new byte[4];
                for (int i = 0; i < 4; i++)
                {
                    arr[i] = Convert.ToByte(ascii.Substring((3 - i) * 2, 2), 16);
                }
                float f = BitConverter.ToSingle(arr, 0);
                return f;
            }
            return 0f;
        }

        //Hex 转换为 float
        public static float HexToFloat(string hex)
        {
            string ascii = HexToAscii(hex);
            float f = AsciiToFloat(ascii);
            return f;
        }

    }
}
